"""
视频音频处理模块
- 查询视频文件中的音频流信息（编解码器、比特率、采样率、声道数）
- 使用 ffmpeg/ffprobe 提取音频；提供 pydub 作为备用方案
"""

import os
import subprocess
import json
from .base_audio import load_audio, save_audio


def get_video_audio_info(video_path: str) -> dict:
    """
    获取视频内第一条音频流的信息
    """
    try:
        cmd = [
            "ffprobe",
            "-v", "quiet",
            "-print_format", "json",
            "-show_streams",
            "-select_streams", "a:0",
            video_path
        ]
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        data = json.loads(result.stdout)
        if 'streams' in data and data['streams']:
            stream = data['streams'][0]
            return {
                'codec_name': stream.get('codec_name', 'unknown'),
                'bit_rate': stream.get('bit_rate', 'unknown'),
                'sample_rate': stream.get('sample_rate', '44100'),
                'channels': stream.get('channels', '2')
            }
        return {'codec_name': 'unknown', 'bit_rate': 'unknown', 'sample_rate': '44100', 'channels': '2'}
    except Exception as e:
        print(f"获取视频音频信息时出错: {str(e)}")
        return {'codec_name': 'unknown', 'bit_rate': 'unknown', 'sample_rate': '44100', 'channels': '2'}


def _get_codec_for_format(audio_format: str) -> str:
    """
    根据目标格式返回合适的编码器名称
    """
    codecs = {
        "mp3": "libmp3lame",
        "aac": "aac",
        "wav": "pcm_s16le",
        "ogg": "libvorbis",
        "flac": "flac",
        "m4a": "aac"
    }
    return codecs.get(audio_format.lower(), "copy")


def _is_format_compatible(original_codec: str, target_format: str) -> bool:
    """
    判断原始编解码器是否与目标容器格式兼容，可直接复制（不重编码）
    """
    compatible_formats = {
        'mp3': ['mp3', 'libmp3lame'],
        'aac': ['aac'],
        'wav': ['pcm_s16le', 'pcm_s24le', 'pcm_f32le'],
        'ogg': ['vorbis', 'libvorbis'],
        'flac': ['flac'],
        'm4a': ['aac']
    }
    return original_codec in compatible_formats.get(target_format.lower(), [])


def extract_audio_from_video(video_path: str, output_path: str, audio_format: str = "mp3", audio_bitrate: str = "192k") -> bool:
    """
    使用 ffmpeg 从视频中提取音频

    参数:
        audio_format: 输出格式（如 mp3、aac、wav 等）
        audio_bitrate: 比特率设置；"original" 直接复制；"original_quality" 尝试使用原始比特率
    """
    try:
        output_dir = os.path.dirname(output_path)
        if output_dir and not os.path.exists(output_dir):
            os.makedirs(output_dir)

        info = get_video_audio_info(video_path)
        original_codec = info.get('codec_name', 'unknown')
        original_bitrate = info.get('bit_rate', 'unknown')
        original_sample_rate = info.get('sample_rate', '44100')

        cmd = ["ffmpeg", "-i", video_path, "-vn"]
        if audio_bitrate == "original" and _is_format_compatible(original_codec, audio_format):
            cmd += ["-acodec", "copy"]
        else:
            cmd += ["-acodec", _get_codec_for_format(audio_format)]
            if audio_bitrate == "original_quality" and original_bitrate != "unknown":
                try:
                    br_value = int(original_bitrate)
                    cmd += ["-ab", "320k"] if audio_format == "mp3" and br_value > 320000 else ["-ab", f"{br_value // 1000}k"]
                except Exception:
                    cmd += ["-ab", "320k"]
            elif audio_bitrate != "original":
                cmd += ["-ab", audio_bitrate]
            cmd += ["-ar", original_sample_rate if original_sample_rate != "unknown" else "44100"]

        cmd += ["-y", output_path]
        subprocess.run(cmd, check=True, capture_output=True)
        return True
    except subprocess.CalledProcessError as e:
        print(f"FFmpeg错误: {e.stderr.decode('utf-8', errors='ignore')}")
        return False
    except Exception as e:
        print(f"提取音频时出错: {str(e)}")
        return False


def extract_audio_with_pydub(video_path: str, output_path: str) -> bool:
    """
    使用 pydub 作为备选方案提取音频（有些容器可能不支持，失败时回退到 ffmpeg）
    """
    try:
        audio = load_audio(video_path)
        save_audio(audio, output_path)
        return True
    except Exception as e:
        print(f"使用pydub提取音频时出错: {str(e)}")
        return extract_audio_from_video(video_path, output_path)